package cn.jilian.sys.service.impl;

import java.lang.reflect.Field;
import java.sql.Date;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import cn.jilian.common.dto.FilterPageSortQuery;
import cn.jilian.common.dto.PageInfo;
import cn.jilian.common.dto.PageResult;
import cn.jilian.common.dto.SortInfo;
import cn.jilian.dao.LinkDAO;
import cn.jilian.dao.MaceDAO;
import cn.jilian.dao.RoleDAO;
import cn.jilian.data.util.DataConverter;
import cn.jilian.entity.Role;
import cn.jilian.sys.service.RoleService;

@Service
public class RoleServiceImpl implements RoleService {

	@Autowired
	private RoleDAO roleDAO;
	@Autowired
	private MaceDAO maceDAO;
	@Autowired
	private LinkDAO linkDAO;
	
	
	@Override
	public long addRole(Role role) {
		role=roleDAO.save(role);
		return role.getId();
	}

	@Override
	public int updateRole(Role role) {
		role=roleDAO.save(role);
		return 0;
	}

	@Override
	public int delete(long id) {
		roleDAO.delete(id);
		maceDAO.deleteByUid(id);
		linkDAO.deleteByRelate(id);
		return 1;
	}

	@Override
	public PageResult<Role> list(FilterPageSortQuery query) {
		PageInfo pageInfo=query.getPageInfo();
		SortInfo sortInfo=query.getSortInfo();
		Map<String,Object> filter=query.getFilter();
		int page=((Number)(pageInfo.getStart()/pageInfo.getLimit())).intValue();
		PageRequest pageRequest=null;
		if(sortInfo!=null) {
			Direction dir=StringUtils.equalsIgnoreCase(sortInfo.getDirect(), "DESC")?Direction.DESC:Direction.ASC;
			pageRequest=new PageRequest(page,pageInfo.getLimit(),dir,sortInfo.getField());
		}else {
			pageRequest=new PageRequest(page,pageInfo.getLimit());
		}
		Page<Role> list=roleDAO.findAll(new Specification<Role>() {

            @Override
            public Predicate toPredicate(Root<Role> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate=cb.conjunction();
                if(filter!=null){
                	for(Map.Entry<String, Object> e:filter.entrySet()) {
                		String key=e.getKey();
                		Object value=e.getValue();
                		try {
                			Field f=Role.class.getDeclaredField(key);
                			Class<?> type=f.getType();
                			if(value!=null) {
                				if(Number.class.isAssignableFrom(type)) {
                					Object v=DataConverter.objectMapper.convertValue(value, type);
                					predicate.getExpressions().add(cb.equal(root.get(key), v));
                				}else if(String.class.isAssignableFrom(type)) {
                					String v=new StringBuilder("%").append(value).append("%").toString();
                					predicate.getExpressions().add(cb.like(root.get(key), v));
                				}else if(Date.class.isAssignableFrom(type)){
                					if(Map.class.isAssignableFrom(value.getClass())) {
                						Map<String,Object> v=(Map<String,Object>)value;
                						if(v.containsKey("start")) {
                							Date start=DataConverter.objectMapper.convertValue(v.get("start"), Date.class);
                							predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get(key), start));
                						}
                						if(v.containsKey("end")) {
                							Date end=DataConverter.objectMapper.convertValue(v.get("end"), Date.class);
                							predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get(key), end));
                						}
                					}else {
                						Date tims=DataConverter.objectMapper.convertValue(value, Date.class);
                						predicate.getExpressions().add(cb.equal(root.get(key), tims));
                					}
                				}
                    			
                    		}
                		}catch(Exception ex) {
                			
                		}
                		
                	}
                   
                }
                return predicate;
            }
        }, pageRequest);
		pageInfo.setCache(list.getSize());
		pageInfo.setTotal(list.getTotalElements());
		return new PageResult<>(pageInfo,list.getContent());
	}

	@Override
	public Role findById(long id) {
		return roleDAO.findOne(id);
	}

}
